#ifndef GAMEENGINE_GRAPHICS_MESHES_MESH_CREATOR_H
#define GAMEENGINE_GRAPHICS_MESHES_MESH_CREATOR_H

#include <GameEngine/Graphics/graphics_settings.h>

#include <GameEngine/Graphics/Meshes/surface_mesh.h>
#include <GameEngine/Geometry/Location/point3d.h>
#include <GameEngine/Geometry/Location/vector3d.h>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

class TextureCoordinate2d;


//! API for the creation of a surface mesh
/*!
 *  This is a base interface for defining surface meshes
 *
 *  The interface has some major shortcomings:<br>
 *  1. The API expects the lines and polygons to be defined as a set of vertex
 *     indexes, which may not be convenient / suitable to some mesh formats.<br>
 *  2. The definition of lines and polygons typically use a state machine
 *     mechanism. Line/polygon definitions are initiated with the appropriate
 *     begin_*() function, and are terminated with the appropriate end_*()
 *     function. Still, this mechanism can be bypassed by overloading these
 *     methods with pass-through functions in derived classes (i.e., the
 *     implementation of these functions in derived classes does nothing).<br>
 *  3. Vertices / normals / texture coordinates must be given one after the
 *     other in a consistent order (e.g., if a mesh contains two vertices v1
 *     and v2 with associated normals n1 and n2, the order of the normals must
 *     be the same as the order of the vertices).
 *
 @todo Some of these limitations are expected to be released in future
       versions of GameEngine
 */
class _Graphics_decl MeshCreator {

public:
	//! Current mode of the surface mesh
	enum Mode {
		//! Neither a line nor a polygon is currently being defined
		None,
		//! A line is currently being defined
		LineDef,
		//! A polygon is currently being defined
		PolygonDef
	};

	MeshCreator();
	MeshCreator(const MeshCreator& rhs);
	MeshCreator& operator=(const MeshCreator& rhs);
	virtual ~MeshCreator();

	//! This function must be called before the mesh starts being built
	/*!
	 @return True if mesh was correctly prepared, false otherwise
	 */
	virtual bool prepare_mesh_creation() = 0;

	//! This function must be called after the mesh has been built
	/*!
	 @return True if mesh was correctly terminated, false otherwise
	 */
	virtual bool finish_mesh_creation() = 0;

	//! Add a vertex to the list of vertices
	/*!
	 @param vertex The vertex to be added
	 @return True if vertex could be added, false otherwise
	 */
	virtual bool add_vertex(const Point3d<float>& vertex) = 0;

	//! Add a normal to the list of normals
	/*!
	 @param normal The normal to be added
	 @return True if normal could be added, false otherwise
	 */
	virtual bool add_normal(const Vector3d<float>& normal) = 0;

	//! Add a texture coordinate to the list of coordinates
	/*!
	 @param coord The texture coordinate to be added
	 @return True if texture coordinate could be added, false otherwise
	 */
	virtual bool add_texture_coordinate(const TextureCoordinate2d& coord) = 0;

	//! Initiates the definition of a polygon
	/*!
	 @return True if polygon could be initiated, false otherwise
	 */
	virtual bool begin_polygon() = 0;

	//! Terminates the definition of a polygon
	/*!
	 @return True if polygon was correctly defined since the previous call
	         of the begin_polygon() function, false otherwise
	 */
	virtual bool end_polygon() = 0;

	//! Initiates the definition of a line
	/*!
	 @return True if line could be initiated, false otherwise
	 */
	virtual bool begin_line() = 0;

	//! Terminates the definition of a line
	/*!
	 @return True if line was correctly defined since the previous call
	         of the begin_line() function, false otherwise
	 */
	virtual bool end_line() = 0;

	//! Add a vertex index to an indexed line or a polygon
	/*!
	 *  This function should be called either between a begin_polygon()
	 *  or a end_polygon() calls, or between a begin_line() and a
	 *  end_line() calls
	 *
	 @return True if vertex index was correctly added, false otherwise
	 */
	virtual bool add_vertex_index(SurfaceMesh::VertexIndex index,
		SurfaceMesh::NormalIndex nindex, SurfaceMesh::TextureCoordinateIndex cindex) = 0;
};


#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#endif
